from turbogears import controllers, expose, flash
import cherrypy
from cherrypy.filters import basefilter

import logging
log = logging.getLogger("jsproxy.controllers")

import httplib

def makeQuery(kwargs):
    """
    Make query element of URI from a supplied dictionary
    """
    return (kwargs and "?"+"&".join([ k+"="+v for (k,v) in kwargs.iteritems()])) or ""

def makePath(path):
    """
    Make path element of URI from a supplied list of segments.
    The leadfing '/' is not included.
    """
    return "/".join(path)

class LeavePostDataFilter(basefilter.BaseFilter):
    """
    Filter supresses parsing of request body - I'm not sure why I have to do this,
    as CherryPy isn't supposed to try and parse field values unless the content-type 
    indicates a suitable form response.
    
    Er, it seems that 'application/x-www-form-urlencoded' is the default content-type
    generated by CURL, or maybe supplied in absence of given content-type?
    """
    def before_request_body(self):
        if cherrypy.request.path[0:6] == '/Proxy':
            # if you don't check that it is a post method the server might lock up
            # we also check to make shour something was submitted
            if not 'Content-Length' in cherrypy.request.headerMap or cherrypy.request.method != 'POST':
                """ the file is empty you might want to redirect"""
            else:
                # Tell CherryPy not to parse the POST data itself for this URL
                cl = cherrypy.request.headers["Content-Length"]
                if cl:
                    cherrypy.request.body = cherrypy.request.rfile.read(int(cl))
                    cherrypy.request.processRequestBody = False

class Proxy:
    """
    Requests proxied to servers on other ports

    Here is a Curl command for texting this:

    curl -H "Content-type: text/plain" -i -d "[\"idle\",[]]" http://localhost:8080/Proxy/8082
    """

    ### Filter not needed if content-type is OK?
    ### _cp_filters = [LeavePostDataFilter()]

    @expose()
    def default(self, *args, **kwargs):
        body = getattr(cherrypy.request, "body", None)
        body = body and body.read()
        logRequest(body, args, kwargs)
        headers = cherrypy.request.headers
        port = int(args[0])
        path = args[1:]
        htc = httplib.HTTPConnection("localhost", port)
        adr = "http://localhost:"+str(port)+"/"
        uri = adr+makePath(path)+makeQuery(kwargs)
        log.debug("Proxy uri %s", uri)
        # request( method, url[, body[, headers]])
        # htc.request("GET", uri, body, headers)
        htc.request(cherrypy.request.method, uri, body)
        rsp = htc.getresponse()
        if not rsp:
            cherrypy.response.status = "500 No response from GET "+adr+uri
            return "500 No response from GET "+adr+uri
        if rsp.status != 200:
            logResponse(rsp)
            cherrypy.response.status = str(rsp.status)+" "+rsp.reason
            return str(rsp.status)+" "+rsp.reason
        cherrypy.response.headers["Cache-control"] = "no-cache"
        cherrypy.response.headers["Pragma"]        = "no-cache"
        cherrypy.response.status = str(rsp.status)+" "+rsp.reason
        rspbody = rsp.read()
        logResponse(rsp, rspbody)
        return rspbody

class Root(controllers.RootController):
    Proxy = Proxy()

    @expose(template="jsproxy.templates.Home")
    def index(self):
        logRequest(None, [], {})
        import time
        # log.debug("Happy TurboGears Controller Responding For Duty")
        flash("Your application is now running")
        return dict(now=time.ctime())

    @expose()
    def default(self, *args, **kwargs):
        body = getattr(cherrypy.request, "body", None)
        body = body and body.read()
        logRequest(body, args, kwargs)
        line = cherrypy.request.requestLine
        body = getattr(cherrypy.request, "body", None)
        headers = cherrypy.request.headers
        return "<h1>Default response</h1>\n<p>%s</p><p>%s</p><p>%s, %s</p>\n"%(line,headers,args,kwargs)

def logRequest(body, *args, **kwargs):
    log.debug("Request %s", cherrypy.request.requestLine)
    log.debug("Method %s, path %s", cherrypy.request.method, cherrypy.request.path)
    log.debug("Args %s, %s", str(args), str(kwargs))
    headers = cherrypy.request.headers.copy()
    strip_headers = ('Remote-Addr', 'Accept-Language', 'Accept-Encoding', 
        'Keep-Alive', 'Remote-Host', 'Host', 'Accept', 'User-Agent', 
        'Accept-Charset', 'Connection', 'Pragma', 'Cache-Control',
        'X-Requested-With', 'referer')
    for k in strip_headers:
        if k in headers: del headers[k]
    log.debug("Headers '%s'", headers)
    log.debug("Request body '%s'", body)
    return

def logResponse(rsp, body=""):
    log.debug("Response %i, %s", rsp.status, rsp.reason)
    log.debug("Headers %s", repr(rsp.getheaders()))
    log.debug("Response body '%s'", body)
    return

